#pragma once
#include "TCPClient.h"
#include "ClientApi.h"
#include "ClientProtocol.h"
#include "User.h"
#include "Storage.h"
#include "Group.h"

using namespace CSApi;

/**
 * Klasa implementująca interfejs ClientApi
 */
class ClientApiImp : public CSApi::ClientApi {
public:
    /**
     * Konstruktor który automatycznie łączy się z serwrem
     * @param ip adres ip
     * @param port port tcp
     * @param username nazwa użytkownika
     * @param password hasło użytkownika
     */
    ClientApiImp(const char* ip, const char* port, const char* username, const char* password);
    
    /**
     * Sprawdza czy plik istnieje
     * @param path scieżka do pliku
     * @return true, jeżeli istnieje, false jeżeli nie istnieje
     */
    bool FileExists(const std::string &path);
    
    /**
     * Otwier plik 
     * @param path scieżka do pliku
     * @param mode tryb otwarcia pliku
     * @return uchwyt do pliku
     */
    THANDLE FileOpen(const std::string &path, const std::string &mode);
    
    /**
     * Zamyka plik
     * @param handle uchwyt do pliku
     * @return true, udało się zamknąć plik, false operacja nie powiodła się
     */
    bool FileClose(THANDLE handle);
    
    /**
     * Pobiera wielkość pliku
     * @param handle uchwyt do pliku
     * @return wielkość pliku
     */
    uint64_t FileSize(THANDLE handle);
    
    /**
     * Pobiera pozycję kursora w pliku
     * @param handle uchwyt do pliku
     * @return pozycja kursora w pliku
     */
    uint64_t FileTell(THANDLE handle);
    
    /**
     * Pobiera czas pliku
     * @param handle uchwyt do pliku
     * @return czas
     */
    uint64_t FileTimestamp(THANDLE handle);
    
    /**
     * Sprawdza czy kursor znajduję się na końcu pliku
     * @param handle uchwyt do pliku
     * @return true kursor jest na końcu pliku
     */
    bool FileEof(THANDLE handle);
    
    /**
     * Zmienia pozycję kursora w pliku
     * @param file uchwyt do pliku
     * @param position nowa pozycja kursora
     * @return status operacji
     */
    bool FileSeek(THANDLE file, int64_t position /*-1 for end*/);
    
    /**
     * Zapisuję dane do pliku
     * @param file uchwyt do pliku
     * @param size rozmiar bufora danych
     * @param data 
     * @return 
     */
    uint32_t FileWrite(THANDLE file, uint32_t size, const uint8_t *data);
    
    /**
     * Odczytuję plik
     * @param file uchwyt do pliku
     * @param size rozmiar buffora danych 
     * @param data buffor danych
     * @return status operacji
     */
    uint32_t FileRead(THANDLE file, uint32_t size, uint8_t *data);
    
    /**
     * Usuwa plik
     * @param path scieżka do pliku
     * @return status operacji
     */
    bool FileDelete(const std::string &path);

    /**
     * Zmienia nazwę pliku
     * @param fileId uchwyt do pliku
     * @param name nowa nazwa pliku
     * @return status operacji
     */
    int32_t RenameFile(uint32_t fileId, string name);

    /**
     * Tworzy katalog
     * @param folderId uchwyt do pliku
     * @param name nazwa tworzonego katalogu
     * @return status operacji
     */
    int32_t MakeDirectory(uint32_t folderId, string name);
    
    /**
     * Usuwa katlog
     * @param folderId uchwyt do katalogu
     * @return status operacji
     */
    int32_t DeleteDirectory(uint32_t folderId);
    
    /**
     * Zmienia nazwę katalogu
     * @param folderId uchwyt do katalogu
     * @param name nazwa katalogu
     * @return status operacji
     */
    int32_t RenameDirectory(uint32_t folderId, string name);
    
    /**
     * Dodaję użytkownika
     * @param name nazwa użytkownika
     * @param password hasło użytkownika
     * @return  status operacji
     */
    int32_t AddUser(string name, string password);
    
    /**
     * Zmienia nazwę użytkownika
     * @param name nazwa użytkownika
     * @param password hasło użytkownika
     * @return status operacji
     */
    int32_t ChangeUserPassword(string name, string password);
    
    /**
     * Usuwa użytkownika
     * @param userId uchwyt do użytkownika
     * @return status operacji
     */
    int32_t RemoveUser(uint32_t userId);
    
    /**
     * Pobiera listę użytkowników
     * @return lista użytkowników
     */
    vector<User> GetUsersList();

    /**
     * Dodaję grupę użytkowników
     * @param name nazwa grupy
     * @return status operacji
     */
    int32_t AddGroup(string name);
    
    /**
     * Usuwa grupę użytkowników
     * @param groupId identyfikator grupy
     * @return status operacji
     */
    int32_t RemoveGroup(uint32_t groupId);
    
    /**
     * Pobiera listę grup
     * @return lista grup
     */
    vector<Group> GetGroupList();

    /**
     * Dodaję magazyn
     * @param name nazwa magayznu
     * @param key klucz magazynu
     * @return 
     */
    int32_t AddStorage(string name, string key);
    
    /**
     * Usuwa magazyn
     * @param storageId identyfikator magazynu
     * @return status operacji
     */
    int32_t RemoveStorage(uint32_t storageId);
    
    /**
     * Zmienia klucz magazynu
     * @param storage nazwa magazynu
     * @param key klucz
     * @return status operacji
     */
    int32_t ChangeStorageKey(string storage, string key);
    
    /**
     * Pobiera listę magazynów
     * @return lista magazynów
     */
    vector<Storage> GetStorageList();

    /**
     * Udostępnia katalog
     * @param virtualPath wirtualna scieżka
     * @param storagePath ścieżka 
     * @param storageName
     * @param force
     * @return 
     */
    bool Share(const std::string &virtualPath, const std::string &storagePath, const std::string &storageName, bool force);
    
    /**
     * Zatrzymuję udostępnianie katalogu
     * @param virtualPath wirtualna scieżka
     * @param remove czy usunąc katalog
     * @return status operacji
     */
    bool UnShare(const std::string &virtualPath, bool remove);

    ~ClientApiImp();

private:
    CSNetworkLib::TCPClient<ClientProtocol> * m_client;
};